Ruby 日記 45日目: 特異クラスを取得する
次のプログラムと同じく特異クラスを取得する選択肢を選んでください。
code:main.rb
class C
def self._singleton
class << C
self
end
end
end
p C._singleton
選択肢:
code:choice01.rb
class C
def self._singleton
class << C
val = self
end
val
end
end
p C._singleton
code:choice02.rb
class C
end
def C._singleton
self
end
p C._singleton
code:choice03.rb
class C
end
class << C
def _singleton
self
end
end
p C._singleton
code:choice04.rb
class C
end
p C.singleton_class
解説:
code:singleton_class.rb
obj = Object.new # obj = nil でも可
class << obj
def test
:
end
:
end
クラス定義と同じ構文で特定のオブジェクトにメソッドやインスタンス変数を 定義/追加します。
この構文の内部で定義したメソッドや定数は指定した オブジェクトに対してだけ有効になります。
そうだったね
で、今回は「特異クラスを取得する」という話なので、特異クラス自身(self)を返すような実装になっている選択肢を選べば良いってわけね。
問題文のコードは
code:main.rb
class C
def self._singleton
class << C
self
end
end
end
p C._singleton
クラスCに対して _singleton というクラスメソッドを定義し、
その中でクラスCの特異クラスを定義して self を返している
なるほどね!
code:bash
# ruby gold/ex45/main.rb
では選択肢を見ていきましょう
/icons/hr.icon
code:choice01.rb
class C
def self._singleton
class << C
val = self
end
val
end
end
p C._singleton
クラスCに対して _singleton というクラスメソッドを定義し、
その中でクラスCの特異クラスを定義している
特異クラスの中では変数valにselfを入れている
けど、その変数 val は特異クラスの中でしか使えないはず
なので、この選択肢は未定義エラーになるんじゃないかな
code:sh
# ruby gold/ex45/choice01.rb
gold/ex45/choice01.rb:6:in _singleton': undefined local variable or method val' for C:Class (NameError)
from gold/ex45/choice01.rb:10:in `<main>'
やはり
/icons/hr.icon
code:choice02.rb
class C
end
def C._singleton
self
end
p C._singleton
クラスCに対して _singleton というクラスメソッドを定義し、
その中で self を返している
単純にクラスCが返ってくるだけかな
code:rb
# ruby gold/ex45/choice02.rb
C
そうだよね
そうだった〜。特異クラスを作らなきゃ〜
/icons/hr.icon
code:choice03.rb
class C
end
class << C
def _singleton
self
end
end
p C._singleton
クラスCに対して特異クラスを定義し、
その中で _singleton というクラスメソッドを定義して self を返している
これって単に、クラスCにクラスメソッドが定義されたのと同じだね
だから、この self はクラスCを返すはず
code:bash
# ruby gold/ex45/choice03.rb
C
ですな
/icons/hr.icon
code:choice04.rb
class C
end
p C.singleton_class
singleton_class -> Class
レシーバの特異クラスを返します。 まだ特異クラスがなければ、新しく作成します。
レシーバが nil か true か false なら、それぞれ NilClass, TrueClass, FalseClass を返します。
なるほど、こういうメソッドがあるわけか。
code:bash
# ruby gold/ex45/choice04.rb
よって、正解は「選択肢4」だね
/icons/hr.icon
特異クラス、例えばこういうことだけど、今のところ使い道が浮かばないな〜
code:sample.rb
class C
end
klass = C.singleton_class
def klass.foo
'klass.foo'
end
p klass.foo # => "klass.foo"
p C.foo # => undefined method `foo' for C:Class (NoMethodError)